#ifndef AFCORE_COMMON_LOG_HELPER_HELPER_FMT_
#define AFCORE_COMMON_LOG_HELPER_HELPER_FMT_

#include <type_traits>

#include "define.h"
#include "logcommon.h"
#include "duration.h"
#include "report.h"

namespace afcore {

/// @brief  日志
namespace log {

/// @brief  转换成fmt字符视图
/// @param  buf     fmt缓存
/// @return 转换后的字符串视图
RStringView ToFmtStringView(const RMemoryBuf& buf) noexcept {
  return RStringView{ buf.data(), buf.size() };
}

/// @brief  向fmt缓存中追加fmt字符视图
/// @param  view    要追加的信息
/// @param  [out]   dest    fmt缓存
void AppendFmtStringView(RStringView view, RMemoryBuf& dest) {
  auto* buf_ptr = view.data();
  dest.append(buf_ptr, buf_ptr + view.size());
}

/// @brief  计算T类型的位数
/// @tparam T   可以转换为整型的类型
/// @param  n   要计算的类型
/// @return 位数
template<typename T>
uint32_t CountDigits(T n) {
  using count_type = typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type;
  return static_cast<uint32_t>(fmt::internal::count_digits(static_cast<count_type>(n)));
}

/// @brief  向fmt缓存中追加可以转化为整数的模板结构
/// @tparam T   可以转换为整型的类型
/// @param  n    可以转化为fmt整数的结构
/// @param  [out]   dest    fmt缓存
template<typename T>
void AppendFmtInt(T n, RMemoryBuf& dest) {
  fmt::format_int i(n);
  dest.append(i.data(), i.data() + i.size());
}

/// @brief  向fmt缓存中追加可以转化为无符号整数的模板结构
/// @tparam T   可以转换为整型的类型
/// @param  n    可以转化为fmt整数的结构
/// @param  width   要填充的宽度
/// @param  [out]   dest    fmt缓存
template<typename T>
void AppendFmtUInt(T n, uint32_t width, RMemoryBuf& dest) {
  DBG_ASSERT(std::is_unsigned<T>::value, "must get unsigned T");
  auto dights = CountDigits(n);
  if (width > dights) {
    /// uint64_t max 18,446,744,073,709,551,615
    const char* zeroes = "0000000000000000000";
    dest.append(zeroes, zeroes + width - dights);
  }
  AppendFmtInt(n, dest);
}

/// @brief  填充长度为2的整数到fmt缓存
/// @tparam T   可以转换为整型的类型
/// @param  n       填充的数
/// @param  [out]   dest    fmt缓存
void Pad2(int n, RMemoryBuf &dest) {
  if (n > 99) {
    AppendFmtInt(n, dest);
  } else if (n > 9) {
    dest.push_back(static_cast<char>('0' + n / 10));
    dest.push_back(static_cast<char>('0' + n % 10));
  } else if (n >= 0) {
    dest.push_back(static_cast<char>('0'));
    dest.push_back(static_cast<char>('0' + n));
  } else {
    fmt::format_to(dest, "{:02}", n);
  }
}

/// @brief  填充长度为3的整数到fmt缓存
/// @tparam T   可以转换为整型的类型
/// @param  n       填充的数
/// @param  [out]   dest    fmt缓存
template<typename T>
void Pad3(T n, RMemoryBuf &dest) {
  AppendFmtUInt(n, 3, dest);
}

/// @brief  填充长度为6的整数到fmt缓存
/// @tparam T   可以转换为整型的类型
/// @param  n       填充的数
/// @param  [out]   dest    fmt缓存
template<typename T>
void Pad6(T n, RMemoryBuf &dest) {
  AppendFmtUInt(n, 6, dest);
}

/// @brief  填充长度为9的整数到fmt缓存
/// @tparam T   可以转换为整型的类型
/// @param  n       填充的数
/// @param  [out]   dest    fmt缓存
template<typename T>
void Pad9(T n, RMemoryBuf &dest) {
  AppendFmtUInt(n, 9, dest);
}

} // !namespace log

} // !namespace afcore

#endif //! AFCORE_COMMON_LOG_HELPER_HELPER_FMT_